#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <mutex>
#include <condition_variable>
#include <queue>
#include <memory>
#include <functional>
#include <thread>

const int INIT_THREAD_SIZE = 8;

class ThreadPool {
public:
    explicit ThreadPool(size_t initThreadSize = INIT_THREAD_SIZE)
        : pool_(std::make_shared<Pool>())
    {
        assert(initThreadSize > 0);
        for(size_t i = 0; i < initThreadSize; ++i) {
            std::thread([pool = pool_](){
                std::unique_lock<std::mutex> lock(pool->mtx_);
                while(true) {
                    // 有任务
                    if(!pool->task_.empty()) {
                        auto task = std::move(pool->task_.front());
                        pool->task_.pop();
                        lock.unlock();
                        task();
                        lock.lock();
                    } else if(pool->isClose_) {
                        break;
                    } else {
                        pool->cond_.wait(lock);
                    }
                }
            }).detach();
        }
    }

    ThreadPool() = default;
    ThreadPool(ThreadPool&&) = default;

    ~ThreadPool() 
    {
        // 进行pool_的空指针检测
        if(static_cast<bool>(pool_)) {
            std::lock_guard<std::mutex> lock(pool_->mtx_);
            pool_->isClose_ = true;
        }
        pool_->cond_.notify_all();
    }

    template <typename T>
    void addTask(T&& task) 
    {
        {
            std::lock_guard<std::mutex> lock(pool_->mtx_);
            pool_->task_.emplace(std::forward<T>(task));
        }
        pool_->cond_.notify_one();
    }
private:
    struct Pool {
        std::mutex mtx_;
        std::condition_variable cond_;
        bool isClose_;
        std::queue<std::function<void()>> task_;
    };
    std::shared_ptr<Pool> pool_;
};

#endif